package com.pool.activity;

import java.util.List;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.pool.R;
import com.pool.activity.common.FullscreenListActivity;
import com.pool.auth.Auth;
import com.pool.common.Record;
import com.pool.common.Shoot;
import com.pool.common.Strings;
import com.pool.store.RecordStore;
import com.pool.store.ShootStore;
import com.pool.store.SpreadsheetsRecordStore;
import com.pool.store.SpreadsheetsShootStore;
import com.pool.store.Store;

/**
 * @author claveld@gmail.com (David Clavel)
 */
public class Synchronize extends FullscreenListActivity {

  private static final String TAG = "Synchronize";
  
  private static final int DIALOG_SPINNER = 0;
  private static final int DIALOG_PROGRESS_BAR = 1;
  private static final int DIALOG_INVALID_AUTH = 2;

  private final Store<Record> temporaryRecordStore;
  private final Store<Record> permanentRecordStore;
  private final Store<Record> onlineRecordStore;
  private final Store<Shoot> localShootStore;
  private final Store<Shoot> onlineShootStore;
  private final Auth auth;
  
  private Thread thread;
  private Boolean hasBeenNotified;
  private ProgressDialog dialog;
  private Handler handler = new Handler() {
    public void handleMessage(Message msg) {
      int dialogId = msg.getData().getInt("dialogId");
      boolean show = msg.getData().getBoolean("show");
      if (show) {
        showDialog(dialogId);
      } else {
        removeDialog(dialogId);
      }
    };
  };
  
  
  public Synchronize() {
    this(RecordStore.usingTemporaryTable(),
         RecordStore.usingPermanentTable(),
         new SpreadsheetsRecordStore(),
         new ShootStore(),
         new SpreadsheetsShootStore(),
         Auth.get());
  }
  
  public Synchronize(Store<Record> temporaryRecordStore,
                     Store<Record> permanentRecordStore,
                     Store<Record> onlineRecordStore,
                     Store<Shoot> localShootStore,
                     Store<Shoot> onlineShootStore,
                     Auth auth) {
    this.temporaryRecordStore = temporaryRecordStore;
    this.permanentRecordStore = permanentRecordStore;
    this.onlineRecordStore = onlineRecordStore;
    this.localShootStore = localShootStore;
    this.onlineShootStore = onlineShootStore;
    this.auth = auth;
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    thread = new Thread() {
      public void run() {
        if (!auth.isAlreadyLogged()) {
          // This should not happen, as LoginAndRun checks for authentication.
          finish();
          return;
        }
        hasBeenNotified = false;
        
        List<Record> shots = temporaryRecordStore.getAll();
        if (shots.size() > 0) {
          sendMessage(true, DIALOG_PROGRESS_BAR);
          synchronized (this) {
            try {
              boolean notified = false;
              synchronized (hasBeenNotified) {
                notified = hasBeenNotified.booleanValue();
              }
              if (!notified) {
                wait(); // for the dialog to be created.
              }
            } catch (InterruptedException e) {
              e.printStackTrace();
            } 
          }
          
          dialog.setMax(shots.size());
          
          for (int i = 0; i < shots.size(); i++) {
            Record record = shots.get(i);
            dialog.setProgress(i);
            dialog.setSecondaryProgress(i);
            if (onlineRecordStore.add(record)) {
              temporaryRecordStore.delete(record);
            } else {
              Log.i(TAG, "Failed!");
              removeDialog(DIALOG_SPINNER);
              finish();
              return;
            }
          }
          dialog.setProgress(dialog.getMax());
          dialog.setSecondaryProgress(dialog.getMax());
        }
        removeDialog(DIALOG_PROGRESS_BAR);
        
        sendMessage(true, DIALOG_SPINNER);
        refresh(onlineShootStore, localShootStore);
        refresh(onlineRecordStore, permanentRecordStore);
        removeDialog(DIALOG_SPINNER);
        finish();
      }
      
      private <E> void refresh(Store<E> onlineStore, Store<E> localStore) {
        List<E> elements = onlineStore.getAll();
        localStore.deleteAll();
        for (E element : elements) {
          localStore.add(element);
        }
      }
      
      private void sendMessage(boolean show, int dialogId) {
        Message showProgressBarMessage = new Message();
        showProgressBarMessage.getData().putBoolean("show", show);
        showProgressBarMessage.getData().putInt("dialogId", dialogId);
        handler.sendMessage(showProgressBarMessage);
      }
    };
    thread.start();
  }

  @Override
  protected Dialog onCreateDialog(int id) {
    switch (id) {
      case DIALOG_PROGRESS_BAR:
        dialog = new ProgressDialog(this);
        dialog.setMessage(Strings.getString(R.string.saving));
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setCancelable(false);
        synchronized (thread) {
          thread.notify();
          synchronized (hasBeenNotified) {
            hasBeenNotified = true; 
          }
        }
        return dialog;
      case DIALOG_SPINNER:
        dialog = new ProgressDialog(this);
        dialog.setMessage(Strings.getString(R.string.synchronizing));
        dialog.setIndeterminate(true);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setCancelable(true);
        return dialog;
      case DIALOG_INVALID_AUTH:
        return new AlertDialog.Builder(this)
            .setTitle(R.string.authentication_failed)
            .setMessage(R.string.invalid_credentials)
            .setPositiveButton(R.string.ok, null)
            .create();
    }
    return null;
  }
}
